package cn.ac.iie.tools;

import java.util.ArrayList;
import java.util.List;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;

@Slf4j
@Component
public class ClickHouseJdbc {

  @Qualifier(value = "clickHouseTemplate")
  private final JdbcTemplate template;

  @Autowired
  public ClickHouseJdbc(JdbcTemplate clickHouseTemplate) {
    this.template = clickHouseTemplate;
  }

  /**
   * 查询列表.
   */
  public <T> List<T> query(String sql, Class<T> t, @Nullable Object... args) {
    try {
      List<T> query = template.query(sql, new BeanPropertyRowMapper<>(t), args);
      log.info("Query List SUCCESS. 【{}】 return size: 【{}】", sql, query.size());
      return query;
    } catch (Exception e) {
      log.error("Query List ERROR. 【{}】", sql, e);
    }
    return new ArrayList<>();
  }

  /**
   * 查询多行单列.
   */
  public List<String> querySingleColumn(String sql, @Nullable Object... args) {
    try {
      //      log.info("QueryForList sql:{}", sql);
      return template.query(sql, (rs, rowNum) -> rs.getString(1), args);
    } catch (Exception e) {
      log.error("queryForList error.", e);
    }
    return new ArrayList<>();
  }

  /**
   * 查询总数.
   */
  public Long count(String sql, @Nullable Object... args) {
    try {
      Long cnt = template.queryForObject(sql, Long.class, args);
      log.info("Query Count SUCCESS. 【{}】 return count: 【{}】", sql, cnt);
      return cnt;
    } catch (Exception e) {
      log.error("Query Count  ERROR. 【{}】", sql, e);
    }
    return 0L;
  }

  /**
   * 查询单个对象.
   */
  public <T> T queryForObject(String sql, Class<T> t) {
    try {
      //      log.info("QueryForObject sql:{}", sql);
      return template.queryForObject(sql, new BeanPropertyRowMapper<>(t));
    } catch (Exception e) {
      log.error("queryForObject error.", e);
    }
    return null;
  }

  /**
   * 执行sql.
   */
  public void execute(String sql) {
    try {
      //      log.info("Execute sql:{}", sql);
      template.execute(sql);
    } catch (Exception e) {
      log.error("execute error.", e);
    }
  }

  /**
   * 执行sql.
   */
  public void update(String sql, @Nullable Object... args) {
    try {
      //      log.info("Execute sql:{}", sql);
      template.update(sql, args);
    } catch (Exception e) {
      log.error("execute error.", e);
    }
  }

  public void batchUpdate(String sql, List<Object[]> args) {
    try {
      int[] ints = template.batchUpdate(sql, args);
      log.info("Batch Update SUCCESS. 【{}】 SIZE: 【{}】", sql, ints.length);
    } catch (Exception e) {
      log.error("Batch Update ERROR. 【{}】", sql, e);
    }
  }
}
